﻿using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Unity.Linq;
using UnityEngine;
using HighlightingSystem;
using UnityEngine.Events;
using UnityEngine.UI;

namespace VIP.Extension
{

    public static class VIPMonoExtension
    {

        /// <summary>
        /// 做一些初始化设置
        /// </summary>
        static VIPMonoExtension()
        {
            //在非编辑器模式下
#if !UNITY_EDITOR
        Debug.unityLogger.logEnabled = false;
#endif
        }

        /// <summary>
        /// 根据名称找到单个子GameObject
        /// </summary>
        /// <param name="selfObj">自身</param>
        /// <param name="name">对象名称</param>
        /// <returns></returns>
        public static GameObject FindChildByName(this GameObject selfObj, string name)
        {
            GameObject obj = selfObj.Descendants().FirstOrDefault(x => x.name == name.Trim());
            return obj ?? null;
        }

        /// <summary>
        /// 根据子物体名字从结尾向前匹配
        /// </summary>
        /// <param name="selfObj">自身</param>
        /// <param name="name">对象名称（从结尾向前匹配）</param>
        /// <returns></returns>
        public static List<GameObject> FindChildEndsWith(this GameObject selfObj, string endStr)
        {
            var objs = selfObj.Children().Where(x => x.name.EndsWith(endStr));
            if (objs == null || objs.Count() == 0) {
                return null;
            }
            return objs.ToList();
        }

        /// <summary>
        /// 根据名称找到子物体集合（模糊查找）
        /// </summary>
        /// <param name="selfObj"></param>
        /// <param name="name"></param>
        /// <returns></returns>
        public static List<GameObject> FindChildrenByName(this GameObject selfObj, string name)
        {
            //IEnumerable<GameObject> objs = selfObj.Descendants().ToList().FindAll(x => x.name.Contains(name.Trim()));
            var objs = selfObj.Descendants().ToList();
            if (objs == null || objs.Count() == 0) {
                return null;
            }
            var target = objs.FindAll(x => x.name.Contains(name.Trim()));
            if (target == null || target.Count() == 0) {
                return null;
            }
            return target.ToList();
        }

        /// <summary>
        /// 返回所有子物体
        /// </summary>
        /// <param name="selfObj"></param>
        /// <param name="withoutGrands">只包括一级子物体</param> 
        /// <returns></returns>
        public static List<GameObject> GetChildren(this GameObject selfObj, bool withoutGrands = true)
        {
            if (withoutGrands)
            {
                return selfObj.Children().ToList();
            }
            else
            {
                return selfObj.Descendants().ToList();
            }
        }

        /// <summary>
        /// 查找具有某个组件的子物体
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static T FindInChildren<T>(this GameObject selfObj) where T : Component
        {
            var children = selfObj.Descendants().ToArray();
            if (children == null || children.Count() == 0)
            {
                return null;
            }
            var target = children.FirstOrDefault(x => x.GetComponent<T>() != null);
            return target == null ? null : target.GetComponent<T>();
        }

        /// <summary>
        /// 在子物体中查找组件集合
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static List<T> FindAllInChildren<T>(this GameObject selfObj) where T : Component
        {

            var children = selfObj.Descendants().ToList();
            if (children == null || children.Count() == 0)
            {
                return null;
            }
            var targets = children.FindAll(x => x.GetComponent<T>() != null);
            if (targets == null || targets.Count == 0)
            {
                return null;
            }
            var results = from target in targets
                          where target.GetComponent<T>() != null
                          select target.GetComponent<T>();
            return results.ToList();
        }

        /// <summary>
        /// 销毁自身
        /// </summary>
        /// <param name="selfObj">自身</param>
        /// <param name="useDestroyImmediate">是否立即对对像进行销毁并从内存中移除</param>
        public static void Destroy(this GameObject selfObj, bool useDestroyImmediate = false)
        {
            if (selfObj == null) return;
            if (useDestroyImmediate)
            {
                GameObject.DestroyImmediate(selfObj);
            }
            else
            {
                GameObject.Destroy(selfObj);
            }
        }

        /// <summary>
        /// 绑定对象的单击事件（依赖EventSystem对象）
        /// </summary>
        /// <param name="selfObj"></param>
        /// <param name="e"></param>
        public static void BindClick(this GameObject selfObj, UnityAction e)
        {
            Button btn = selfObj.GetComponent<VIPButton>();
            if (btn.IsNull())
            {
                Debug.LogError("给对象绑定单击事件需要给对象添加VIPButton组件");
                return;
            }
            btn.onClick.AddListener(e);
        }

        /// <summary>
        /// 绑定对象的按下事件（依赖EventSystem对象）
        /// </summary>
        /// <param name="selfObj"></param>
        /// <param name="e"></param>
        public static void BindDownClick(this GameObject selfObj, UnityAction e)
        {
            VIPButton btn = selfObj.GetComponent<VIPButton>();
            if (btn.IsNull())
            {
                Debug.LogError("给对象绑定单击事件需要给对象添加VIPButton组件");
                return;
            }
            btn.onDown.AddListener(e);
        }

        /// <summary>
        /// 绑定对象的抬起事件（依赖EventSystem对象）
        /// </summary>
        /// <param name="selfObj"></param>
        /// <param name="e"></param>
        public static void BindUpClick(this GameObject selfObj, UnityAction e)
        {
            VIPButton btn = selfObj.GetComponent<VIPButton>();
            if (btn.IsNull())
            {
                Debug.LogError("给对象绑定单击事件需要给对象添加VIPButton组件");
                return;
            }
            btn.onUp.AddListener(e);
        }

        /// <summary>
        /// 绑定对象的进入事件（依赖EventSystem对象）
        /// </summary>
        /// <param name="selfObj"></param>
        /// <param name="e"></param>
        public static void BindEnterClick(this GameObject selfObj, UnityAction e)
        {
            VIPButton btn = selfObj.GetComponent<VIPButton>();
            if (btn.IsNull())
            {
                Debug.LogError("给对象绑定单击事件需要给对象添加VIPButton组件");
                return;
            }
            btn.onEnter.AddListener(e);
        }

        /// <summary>
        /// 绑定对象的退出事件（依赖EventSystem对象）
        /// </summary>
        /// <param name="selfObj"></param>
        /// <param name="e"></param>
        public static void BindExitClick(this GameObject selfObj, UnityAction e)
        {
            VIPButton btn = selfObj.GetComponent<VIPButton>();
            if (btn.IsNull())
            {
                Debug.LogError("给对象绑定单击事件需要给对象添加VIPButton组件");
                return;
            }
            btn.onExit.AddListener(e);
        }

        /// <summary>
        /// 绑定对象的长按事件（依赖EventSystem对象）
        /// </summary>
        /// <param name="selfObj"></param>
        /// <param name="e"></param>
        public static void BindLongClick(this GameObject selfObj, UnityAction e)
        {
            VIPButton btn = selfObj.GetComponent<VIPButton>();
            if (btn.IsNull())
            {
                Debug.LogError("给对象绑定单击事件需要给对象添加VIPButton组件");
                return;
            }
            btn.onLong.AddListener(e);
        }

        /// <summary>
        /// 绑定对象的双击事件（依赖EventSystem对象）
        /// </summary>
        /// <param name="selfObj"></param>
        /// <param name="e"></param>
        public static void BindDoubleClick(this GameObject selfObj, UnityAction e)
        {
            VIPButton btn = selfObj.GetComponent<VIPButton>();
            if (btn.IsNull())
            {
                Debug.LogError("给对象绑定单击事件需要给对象添加VIPButton组件");
                return;
            }
            btn.onDouble.AddListener(e);
        }

        /// <summary>
        /// 显示GameObject
        /// </summary>
        /// <param name="selfObj">自身</param>
        public static void Show(this GameObject selfObj)
        {
            selfObj.transform.Show();
        }

        /// <summary>
        /// 显示GameObject
        /// </summary>
        /// <param name="selfObj">自身</param>
        /// <param name="v3"></param>
        /// <returns></returns>
        public static void Show(this GameObject selfObj, Vector3 v3)
        {
            selfObj.transform.Show(v3);
        }

        /// <summary>
        /// 隐藏GameObject
        /// </summary>
        /// <param name="selfObj">自身</param>
        public static void Hide(this GameObject selfObj)
        {
            selfObj.transform.Hide();
        }

        /// <summary>
        /// 激活GameObject
        /// </summary>
        /// <param name="selfObj">自身</param>
        /// <returns></returns>
        public static void Enable(this GameObject selfObj)
        {
            selfObj.SetActive(true);
        }

        /// <summary>
        /// 禁用GameObject
        /// </summary>
        /// <param name="selfObj">自身</param>
        /// <returns></returns>
        public static void Disable(this GameObject selfObj)
        {
            selfObj.SetActive(false);
        }

        /// <summary>
        /// 开启边缘发光（需要在对象身上添加Highlighter组件，在相机上添加Highlighting Renderer组件）
        /// </summary>
        /// <param name="selfObj">自身</param>
        /// <returns></returns>
        public static GameObject HighlighterOn(this GameObject selfObj)
        {
            Highlighter highlighter = selfObj.GetComponent<Highlighter>();
            if (highlighter.IsNull())
            {
                Debug.LogError("使用对象边缘发光需要在对象上挂载Highlighter组件");
                return null;
            }
            highlighter.ConstantOn();
            return selfObj ?? null;
        }

        /// <summary>
        /// 关闭边缘发光（需要在对象身上添加Highlighter组件，在相机上添加Highlighting Renderer组件）
        /// </summary>
        /// <param name="selfObj">自身</param>
        /// <returns></returns>
        public static GameObject HighlighterOff(this GameObject selfObj)
        {
            Highlighter highlighter = selfObj.GetComponent<Highlighter>();
            if (highlighter.IsNull())
            {
                Debug.LogError("使用对象边缘发光需要在对象上挂载Highlighter组件");
                return null;
            }
            highlighter.ConstantOff();
            return selfObj ?? null;
        }

        /// <summary>
        /// 显示Tranform
        /// </summary>
        /// <param name="selfTf"></param>
        public static void Show(this Transform selfTf)
        {
            selfTf.localScale = Vector3.one;
        }

        /// <summary>
        /// 显示Tranform
        /// </summary>
        /// <param name="selfTf"></param>
        /// <param name="v3"></param>
        public static void Show(this Transform selfTf, Vector3 v3)
        {
            selfTf.localScale = v3;
        }

        /// <summary>
        /// 隐藏Tranform
        /// </summary>
        /// <param name="selfTf"></param>
        public static void Hide(this Transform selfTf)
        {
            selfTf.localScale = Vector3.zero;
        }

        /// <summary>
        /// 使用CanvasGroup组件显示Transform
        /// </summary>
        /// <param name="selfTf">自身</param>
        /// <param name="tf"></param>
        public static void CGShow(this Transform selfTf)
        {
            CanvasGroup cg = selfTf.GetComponent<CanvasGroup>();
            if (cg.IsNull())
            {
                Debug.LogError("tranform.CGShow/CGHide方法需要挂载CanvasGroup组件");
                return;
            }
            cg.alpha = 1;
            cg.interactable = true;
            cg.blocksRaycasts = true;
        }

        /// <summary>
        /// 使用CanvasGroup组件隐藏Transform
        /// </summary>
        /// <param name="selfTf">自身</param>
        public static void CGHide(this Transform selfTf)
        {
            CanvasGroup cg = selfTf.GetComponent<CanvasGroup>();
            if (cg.IsNull())
            {
                Debug.LogError("tranform.CGShow/CGHide方法需要挂载CanvasGroup组件");
                return;
            }
            cg.alpha = 0;
            cg.interactable = false;
            cg.blocksRaycasts = false;
        }

        /// <summary>
        /// 复位本地坐标 position、rotision、scale 三个值
        /// </summary>
        /// <param name="selfObj">自身</param>
        /// <returns></returns>
        public static Transform Reset(this Transform selfTf)
        {
            selfTf.localPosition = Vector3.zero;
            selfTf.localEulerAngles = Vector3.zero;
            selfTf.localScale = Vector3.one;
            return selfTf ?? null;
        }

        /// <summary>
        /// 单独改变localPosition的x轴的值
        /// </summary>
        /// <param name="selfTf"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static Transform localPositionX(this Transform selfTf, float value)
        {
            selfTf.localPosition = selfTf.localPosition.X(value);
            return selfTf;
        }

        /// <summary>
        /// 单独改变localPosition的y轴的值
        /// </summary>
        /// <param name="selfTf"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static Transform localPositionY(this Transform selfTf, float value)
        {
            selfTf.localPosition = selfTf.localPosition.Y(value);
            return selfTf;
        }

        /// <summary>
        /// 单独改变localPosition的z轴的值
        /// </summary>
        /// <param name="selfTf"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static Transform localPositionZ(this Transform selfTf, float value)
        {
            selfTf.localPosition = selfTf.localPosition.Z(value);
            return selfTf;
        }

        /// <summary>
        /// 单独改变localEulerAngles的x轴的值
        /// </summary>
        /// <param name="selfTf"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static Transform localEulerAnglesX(this Transform selfTf,Vector3 start, float value)
        {
            start.x = value;
            selfTf.localEulerAngles = start;
            return selfTf;
        }

        /// <summary>
        /// 单独改变localEulerAngles的y轴的值
        /// </summary>
        /// <param name="selfTf"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static Transform localEulerAnglesY(this Transform selfTf ,Vector3 start , float value)
        {
            start.y = value;
            selfTf.localEulerAngles = start;
            return selfTf;
        }

        /// <summary>
        /// 单独改变localEulerAngles的z轴的值
        /// </summary>
        /// <param name="selfTf"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static Transform localEulerAnglesZ(this Transform selfTf,Vector3 start, float value)
        {
            start.z = value;
            selfTf.localEulerAngles = start;
            return selfTf;
        }

        /// <summary>
        /// 单独改变localScale的x轴的值
        /// </summary>
        /// <param name="selfTf"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static Transform localScaleX(this Transform selfTf, float value)
        {
            selfTf.localScale = selfTf.localScale.X(value);
            return selfTf;
        }

        /// <summary>
        /// 单独改变localScale的y轴的值
        /// </summary>
        /// <param name="selfTf"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static Transform localScaleY(this Transform selfTf, float value)
        {
            selfTf.localScale = selfTf.localScale.Y(value);
            return selfTf;
        }

        /// <summary>
        /// 单独改变localScale的z轴的值
        /// </summary>
        /// <param name="selfTf"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static Transform localScaleZ(this Transform selfTf, float value)
        {
            selfTf.localScale = selfTf.localScale.Z(value);
            return selfTf;
        }

        /// <summary>
        /// 单独改变x轴值
        /// </summary>
        /// <param name="selfV3"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        private static Vector3 X(this Vector3 selfV3, float value)
        {
            Vector3 v3;
            v3 = selfV3;
            v3.x = value;
            return v3;
        }

        /// <summary>
        /// 单独改变y轴值
        /// </summary>
        /// <param name="selfV3"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        private static Vector3 Y(this Vector3 selfV3, float value)
        {
            Vector3 v3;
            v3 = selfV3;
            v3.y = value;
            return v3;
        }

        /// <summary>
        /// 单独改变z轴值
        /// </summary>
        /// <param name="selfV3"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        private static Vector3 Z(this Vector3 selfV3, float value)
        {
            Vector3 v3;
            v3 = selfV3;
            v3.z = value;
            return v3;
        }

    }

}
